#pragma once

#include "IFont.h"


class CVertexBuffer;
class CIndexBuffer;

class CFont: public IFont, public IRenderObjectBase
{
public:
	CFont(const char* name, uint size);
	~CFont();

	bool Init();

	//	IFont
	virtual void RenderText(const char* text, float x, float y, const Color& color);
	virtual Vec2 MeasureString(const char* text) const;
	virtual uint GetLineSpacing();

	virtual void Flush();
	//	---

private:
	void SetupIndexBuffer();
	void LoadGlyps();
	void LoadGlyph(uint glyph_index);
	void DestroyGlyphs();
	void DestroyGlyph(uint glyph_index);
	void GenerateTexture(uint width, uint height);

private:
	static const uint FIRST_GLYPH = '!';	//	first glyph to cache
	static const uint GLYPHS_COUNT = 128;
	static const uint SCREEN_DPI = 96;
	static const uint TEXTURE_OFFSET = 1;	//	offset between glyphs in font texture
	static const uint MAX_TEXTURE_SIZE = 2048;
	static const uint STRING_BUFFER_SIZE = 2048;	//	render text buffer size (in characters)
	static const uint SPACE_INDEX = ' ';

	static const uint BYTES_PER_SYMBOL = sizeof(S2DVertex)*4;
	static const uint VERTEX_BUFFER_SIZE = STRING_BUFFER_SIZE*BYTES_PER_SYMBOL;
	static const uint INDEX_BUFFER_SIZE = STRING_BUFFER_SIZE*sizeof(uint16)*6;
	static const uint STRING_BUFFER_VERTICES = STRING_BUFFER_SIZE*4;

	struct SGlyphSlot
	{
		Vec2i	bearing;	//	offset from pen position to bbox edge
		Vec2i	advance;	//	offset to the next pen position
		Rect	bbox;

		Vec2i pos[2];		//	texture coordinates in pixels
		Vec2	uv[2];		//	texture coordinates in range [0.0f, 1.0f], [0] - left-top, [1] - right-bottom
	};

private:
	FT_Library	m_FTLib;
	FT_Face			m_FTFace;

	uint				m_size;
	string			m_name;
	bool				m_kerning;
	SGlyphSlot	m_slots[GLYPHS_COUNT];
	FT_Glyph		m_glyphs[GLYPHS_COUNT];
	uint				m_ascender;	//	distance from baseline to baseline
	uint				m_line_spacing;	//	distance to the next line of text

	TextureId		m_texture;

	IVertexBuffer*	m_vertices;
	IIndexBuffer*		m_indices;

	S2DVertex		m_vbuffer[STRING_BUFFER_VERTICES];
	uint				m_symbols_buffered;	//	symbols buffered for render
};